package com.bbs.security;

import com.bbs.pojo.User;
import com.bbs.pojo.UserPrincipal;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.security.Key;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

@Component
public class TokenProvider implements InitializingBean {
    private JwtBuilder jwtBuilder;
    private JwtParser jwtParser;

    @Override
    public void afterPropertiesSet() throws Exception {
        //创建jwtBuilder,设置盐值以及加密算法
        byte[] keyBytes = "haihaihai是的规划设计看东方帝国海军的思考法律规定阿斯顿发射点发大水发大水发射点的发射点".getBytes(StandardCharsets.UTF_8);
        Key key = Keys.hmacShaKeyFor(keyBytes);
        this.jwtBuilder = Jwts.builder().signWith(key, SignatureAlgorithm.HS512);

        //创建jwtParser，设置盐值
        this.jwtParser = Jwts.parserBuilder().setSigningKey(key).build();
    }

    /**
     * 生成Jwt
     * @param user Principal 即用户
     * @param rememberMe 是否保存长期登录
     * @return Jwt
     */
    public String createToken(UserPrincipal user, boolean rememberMe){
        if(user != null){
            Date issuedTime = new Date();
            Date expirationTime = null;
            if(rememberMe){
                expirationTime = new Date(issuedTime.getTime() + AuthProperties.rememberMeValidTime * 1000);
            }else{
                expirationTime = new Date(issuedTime.getTime() + AuthProperties.tokenValidTime * 1000);
            }

            //Jwt
            return jwtBuilder
                    .setId(UUID.randomUUID().toString())
                    .setIssuer("LaoBa")                         //签发者
                    .setIssuedAt(issuedTime)                    //签发时间
                    .setExpiration(expirationTime)              //过期时间
                    .setSubject(user.getUserId())               //主体标识
                    .claim("username", user.getUsername())
                    .claim("role", user.getRole())
                    .claim("laoba", "haihaihai")
                    .compact();
        }else{
            return null;
        }
    }

    /**
     * 解析token获取认证对象
     * @param token
     * @return
     */
    public Authentication parserToken(String token){
        //TODO: 异常处理
        try{
            Claims claims = jwtParser.parseClaimsJws(token).getBody();
            UserPrincipal principal = new UserPrincipal();
            principal.setUserId(claims.getSubject());
            principal.setUsername(claims.get("username", String.class));
            principal.setRole(claims.get("role", String.class));

            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority(principal.getRole()));

            return new UsernamePasswordAuthenticationToken(principal, null, authorities);
        }catch (JwtException e){
            e.printStackTrace();
        }

        return null;
    }
}
